#pragma once 

#include <iostream>
using namespace std;
#include <sys/select.h>
#include <unistd.h>
#include <string>
#include "Sock.hpp"
#include "log.hpp"

class SelectServer
{
  private:
    uint16_t _port;
    int _listensock;
  public:
    SelectServer(const uint16_t& port = 8081)
      :_port(port)
    {
      _listensock = Sock::Socket();
      Sock::Bind(_listensock , _port); 
      Sock::Listen(_listensock);
      logMessage(DEBUG , "create base socket success");
    }

    ~SelectServer()
    {
      if (_listensock > 0)
      {
        close(_listensock);
      }
    }

  public:
    void Start()
    {
      fd_set rfds;
      FD_ZERO(&rfds);
      // struct timeval timeout = {5 , 0};
      while (true)
      {
        // int sock = Sock::Accept(_listensock , ...);
        FD_SET(_listensock , &rfds);
        int n = select(_listensock + 1 , &rfds , nullptr , nullptr , nullptr);
        switch (n)
        {
          case 0:
            logMessage(DEBUG , "time out..");
            break;
          case -1:
            logMessage(WARNING , "select error: %d : %s" , errno , strerror(errno));
          default:
            sleep(1);
            logMessage(DEBUG , "get a new link...");
            HandlerEvent(rfds);
            break;
        }
      }
    }

  private: 
    void HandlerEvent(const fd_set& rfds)
    {
      string clientip;
      uint16_t clientport = 0;
      if (FD_ISSET(_listensock , &rfds))
      {
        int sock = Sock::Accept(_listensock , &clientip , &clientport);
        if (sock < 0)
        {
          logMessage(WARNING , "Accept error");
          return;
        }
        logMessage(DEBUG , "get a new line success :[%s : %d] , %d" , clientip.c_str() , clientport , sock);
      }
    }
};



